using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Browser;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Navigation;
using Lib.Approval;
using Lib.Helper;
using Lib.Mail;
using MSIACCSL2.ApplicationStateServices;
using MSIACCSL2.Command;
using MSIACCSL2.CurrencyServices;
using MSIACCSL2.PurchaseOrderServices;
using MSIACCSL2.SubGroupServices;
using MSIACCSL2.SupplierServices;
using MSIACCSL2.Views.PurchaseOrder;
using MSIACCSL2.WarehouseServices;
using WcfService1.DTO;
using GetListByCriteriaCompletedEventArgs = MSIACCSL2.PurchaseOrderServices.GetListByCriteriaCompletedEventArgs;
using GetListCompletedEventArgs = MSIACCSL2.PurchaseOrderServices.GetListCompletedEventArgs;
using SaveCompletedEventArgs = MSIACCSL2.PurchaseOrderServices.SaveCompletedEventArgs;

namespace MSIACCSL2.ViewModels
{
    public class PurchaseOrderViewModel : ViewModelBase
    {
        #region Delegates

        public delegate void Completed(Object param);

        #endregion

        private static Search frmSearch;
        private static string OrderType;
        private static string PropertySort;
        public static Mode mode;
        private static FrmAdd frmAdd;
        public static Completed OnSearchCompleted;
        private static NavigationService _NavigationService;
        private readonly AplicationStateServicesClient ApplicationService;


        private readonly CurrencyServicesClient CurrencyClient;
        private readonly SubGroupServiceClient SubGroupClient;
        private readonly SupplierServicesClient SupplierClient;
        private readonly WarehouseServicesClient WarehouseClient;
        private readonly ValidationHandler validationHandler;
        private int CurrentPage;
        private bool IsUsed;
        private ObservableCollection<int> Pages;
        private ObservableCollection<CurrencyDTO> _Currencys;
        private bool _IsBusy;
        private bool _IsEnabled;
        private PurchaseOrderDTO _PurchaseOrder;
        private PagedCollectionView _PurchaseOrders;
        private Visibility _SupplierVisibility;
        private ObservableCollection<SupplierDTO> _Suppliers;
        private ObservableCollection<WarehouseDTO> _Warehouses;
        private List<string> _errors;
        private Visibility _messageVisibility;
        private PagedCollectionView _pageSources;
        private PurchaseOrderServicesClient client;
        private Dictionary<string, object> criteria;
        private string expression;

        public PurchaseOrderViewModel()
        {
            WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
            SupplierVisibility = Visibility.Collapsed;
            IsEnabled = true;

            if (!DesignerProperties.IsInDesignTool)
            {
                client = new PurchaseOrderServicesClient();
                SupplierClient = new SupplierServicesClient();
                WarehouseClient = new WarehouseServicesClient();
                CurrencyClient = new CurrencyServicesClient();
                SubGroupClient = new SubGroupServiceClient();
                OnPageChanged = new DelegateCommand(PageIndexChanged, CanPageIndexChanged);
                Save = new DelegateCommand(SavePurchaseOrder, CanSave);
                New = new DelegateCommand(NewPurchaseOrder, CanNew);
                Unload = new DelegateCommand(Release, CanUnload);
                SearchCommand = new DelegateCommand(SearchPurchaseOrder, CanSearch);
                SearchResultCommand = new DelegateCommand(SearchResult, CanSearchResult);
                CancelCommand = new DelegateCommand(Cancel, CanCancelCommand);
                validationHandler = new ValidationHandler();
                MessageVisibility = Visibility.Collapsed;
                ApplicationService = new AplicationStateServicesClient();

                if (mode == Mode.Edit)
                {
                    PrepareEdit();
                }
                else if (mode == Mode.Search)
                {
                    PurchaseOrder = new PurchaseOrderDTO();
                    PurchaseOrder.PODate = null;
                    GetWarehouseList();
                    GetCurrencyList();
                }
                else if (mode == Mode.Add)
                {
                    PrepareAdd();
                }
                else
                {
                    GetList(1, null);
                }
            }
        }


        public PagedCollectionView PurchaseOrders
        {
            get { return _PurchaseOrders; }

            private set
            {
                if (PurchaseOrders == value) return;
                _PurchaseOrders = value;
                int i = (CurrentPage*30);
                foreach (object PurchaseOrder in PurchaseOrders)
                {
                    i += 1;

                    ((PurchaseOrderDTO) PurchaseOrder).No = i;
                }
                FirePropertyChanged("PurchaseOrders");
                PurchaseOrders.CollectionChanged += PurchaseOrder_CollectionChanged;
            }
        }

        public PagedCollectionView PageSources
        {
            get { return _pageSources; }
            private set
            {
                if (PageSources == value) return;
                _pageSources = value;
                FirePropertyChanged("PageSources");
            }
        }


        public ObservableCollection<SupplierDTO> Suppliers
        {
            get { return _Suppliers; }
            private set
            {
                if (Suppliers == value) return;
                _Suppliers = value;
                FirePropertyChanged("Suppliers");
            }
        }


        public ObservableCollection<WarehouseDTO> Warehouses
        {
            get { return _Warehouses; }
            private set
            {
                if (Warehouses == value) return;
                _Warehouses = value;
                FirePropertyChanged("Warehouses");
            }
        }


        public ObservableCollection<CurrencyDTO> Currencys
        {
            get { return _Currencys; }
            private set
            {
                if (Currencys == value) return;
                _Currencys = value;
                FirePropertyChanged("Currencys");
            }
        }


        public bool IsBusy
        {
            get { return _IsBusy; }
            internal set
            {
                _IsBusy = value;
                FirePropertyChanged("IsBusy");
            }
        }

        public Visibility SupplierVisibility
        {
            get { return _SupplierVisibility; }
            internal set
            {
                _SupplierVisibility = value;
                FirePropertyChanged("SupplierVisibility");
            }
        }


        public long RecordCount { get; set; }

        //Buat binding ke child form waktu mau edit
        public PurchaseOrderDTO PurchaseOrder
        {
            get { return _PurchaseOrder; }
            private set
            {
                if (PurchaseOrder == value) return;
                _PurchaseOrder = value;
                FirePropertyChanged("PurchaseOrder");
            }
        }


        public ICommand OnPageChanged { get; set; }
        public ICommand Save { get; set; }
        public ICommand New { get; set; }
        public ICommand Edit { get; set; }
        public ICommand Unload { get; set; }
        public ICommand SearchCommand { get; set; }
        public ICommand SearchResultCommand { get; set; }
        public ICommand CancelCommand { get; set; }

        public List<string> Errors
        {
            get { return _errors; }
            private set
            {
                if (Errors == value) return;
                _errors = value;
                FirePropertyChanged("Errors");
            }
        }


        public Visibility MessageVisibility
        {
            get { return _messageVisibility; }
            private set
            {
                if (MessageVisibility == value) return;
                _messageVisibility = value;
                FirePropertyChanged("MessageVisibility");
            }
        }

        public bool IsEnabled
        {
            get { return _IsEnabled; }
            internal set
            {
                _IsEnabled = value;
                FirePropertyChanged("IsEnabled");
            }
        }

        private void PrepareEdit()
        {
            PurchaseOrder = (PurchaseOrderDTO) Navigation.Args;
            GetPurchaseOrder(PurchaseOrder.PONumber);
            CekTransaksi();
        }


        private void PrepareAdd()
        {
            //GetLastNoMutasi();
            GetWarehouseList();
            GetCurrencyList();
            PurchaseOrder = new PurchaseOrderDTO();
            PurchaseOrder.PurchaseOrderDetails = new ObservableCollection<PurchaseOrderDetailDTO>();
            var PurchaseOrderDetail = new PurchaseOrderDetailDTO();
            PurchaseOrderDetail.SubGroup = new SubGroupDTO();
            PurchaseOrder.PurchaseOrderDetails.Add(PurchaseOrderDetail);
            //CekTransaksi();
        }

        private void GetPurchaseOrder(string PONumber)
        {
            IsBusy = true;
            client.GetPurchaseOrderCompleted += client_GetPurchaseOrderCompleted;
            client.GetPurchaseOrderAsync(PONumber);
        }

        private void client_GetPurchaseOrderCompleted(object sender, GetPurchaseOrderCompletedEventArgs e)
        {
            client.GetPurchaseOrderCompleted -= client_GetPurchaseOrderCompleted;
            PurchaseOrder = e.Result;
            if (PurchaseOrder.Status == Status.Void || PurchaseOrder.Status == Status.Close) IsEnabled = false;
            PurchaseOrder.PurchaseOrderDetails = PurchaseOrder.PurchaseOrderDetails;
            LoadSubGroupList();
            GetWarehouseList();
            GetCurrencyList();
            IsBusy = false;
        }


        private void LoadSubGroupList()
        {
            foreach (PurchaseOrderDetailDTO purchaseOrderDetail in PurchaseOrder.PurchaseOrderDetails)
                if (purchaseOrderDetail.PurchaseOrderDetailId != 0)
                {
                    purchaseOrderDetail.Subgroups = new ObservableCollection<SubGroupDTO>();
                    purchaseOrderDetail.Subgroups.Add(purchaseOrderDetail.SubGroup);
                }
        }

        public void Complete(Object param)
        {
            OnSearchCompleted(param);
        }

        private void PurchaseOrder_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (((PagedCollectionView) sender).SortDescriptions.Count > 0)
            {
                if (((PagedCollectionView) sender).SortDescriptions[0].PropertyName.ToLower() == "no") return;

                PropertySort = ((PagedCollectionView) sender).SortDescriptions[0].PropertyName;
                if (string.IsNullOrEmpty(OrderType))
                {
                    OrderType = "ASC";
                }
                else
                {
                    OrderType = OrderType == "ASC" ? OrderType = "DESC" : OrderType = "ASC";
                }
                GetList(1, PropertySort);
            }
        }


        public void SavePurchaseOrder(Object purchaseOrder)
        {
            //PurchaseOrder = (PurchaseOrderDTO) purchaseOrder;
            if (PurchaseOrder.PurchaseOrderDetails.Count == 1)
            {
                //Bila tidak ada yang dipilih di detail maka details harus dihapus
                if (PurchaseOrder.PurchaseOrderDetails[0].SubGroup == null)
                    PurchaseOrder.PurchaseOrderDetails.Clear();
            }
            Validate();
            if (Errors.Count > 0) return;
            PurchaseOrder.created_by = GlobalVar.User.UserID;
            PurchaseOrder.modified_by = GlobalVar.User.UserID;
            IsBusy = true;
            client.SaveCompleted += client_SaveCompleted;
            client.SaveAsync(PurchaseOrder, mode);
        }

        private void client_SaveCompleted(object sender, SaveCompletedEventArgs e)
        {
            if (e.Error != null) Validate(e.Error.ToString());
            client.SaveCompleted -= client_SaveCompleted;
            mode = (Mode) e.UserState;
            if (e.Result)
            {
                IsBusy = false;
                ClearTransaksi(mode);
                mode = Mode.Idle;
                Navigation.MyNavigation.Navigate(new Uri("/PurchaseOrder/Index", UriKind.Relative));
            }
            else
            {
                IsBusy = false;
                MessageBox.Show("Simpan Gagal, Periksa data Anda!");
            }
        }


        public void GetList(int? page, string sortProp)
        {
            IsBusy = true;
            client.GetListCompleted += client_GetListCompleted;
            client.GetListAsync(page ?? 1, sortProp, OrderType);
        }

        private void client_GetListCompleted(object sender, GetListCompletedEventArgs e)
        {
            RecordCount = e.recordCount;
            if (PageSources == null) CreatePageNumber();
            client.GetListCompleted -= client_GetListCompleted;
            PurchaseOrders = new PagedCollectionView(e.Result);
            IsBusy = false;
            Complete(this);
        }


        private void NewPurchaseOrder(Object param)
        {
            mode = Mode.Add;
            Navigation.MyNavigation = (NavigationService) param;
            Navigation.MyNavigation.Navigate(new Uri("/PurchaseOrder/frmAdd", UriKind.Relative));
        }


        private void SearchPurchaseOrder(Object param)
        {
            mode = Mode.Search;
            frmSearch = new Search();
            frmSearch.Show();
        }


        private void SearchResult(Object param)
        {
            var criteria = new Dictionary<string, object>();

            foreach (PropertyInfo prop in PurchaseOrder.GetType().GetProperties())
            {
                if (prop.PropertyType == typeof (Decimal))
                    if ((Decimal) prop.GetValue(PurchaseOrder, null) == 0) continue;
                if (prop.PropertyType == typeof (Int32))
                    if ((Int32) prop.GetValue(PurchaseOrder, null) == 0) continue;
                if (prop.PropertyType == typeof (Int64))
                    if ((Int64) prop.GetValue(PurchaseOrder, null) == 0) continue;
                if (prop.PropertyType == typeof (Double))
                    if ((Double) prop.GetValue(PurchaseOrder, null) == 0) continue;
                if (prop.PropertyType == typeof (String))
                    if (String.IsNullOrEmpty((String) prop.GetValue(PurchaseOrder, null))) continue;
                if (prop.PropertyType == typeof (DateTime))
                    if (prop.GetValue(PurchaseOrder, null).ToString().Contains("0001")) continue;
                if (prop.GetValue(PurchaseOrder, null) == null) continue;
                if (prop.PropertyType.Name == "No") continue;

                if (prop.PropertyType.Name.ToLower().Contains("dto"))
                    foreach (PropertyInfo propertyInfo in
                        prop.GetValue(PurchaseOrder, null).GetType().GetProperties().Where(
                            propertyInfo =>
                            propertyInfo.Name.ToLower().Contains("id") || propertyInfo.Name.ToLower().Contains("kode") ||
                            propertyInfo.Name.ToLower().Contains("serial") ||
                            propertyInfo.Name.ToLower().Contains("code")))
                    {
                        criteria.Add(prop.Name, propertyInfo.GetValue(prop.GetValue(PurchaseOrder, null), null));
                        break;
                    }
                else
                    criteria.Add(prop.Name, prop.GetValue(PurchaseOrder, null));
            }

            string expression = string.Empty;
            if (frmSearch.rblOr.IsChecked ?? false) expression = "OR";
            else expression = "AND";
            PurchaseOrderSearch(criteria, expression,1);
        }

        private void PurchaseOrderSearch(Dictionary<String, Object> criteria, string expression,int page)
        {
            if (criteria.ContainsKey("Status")) criteria.Remove("Status");
            frmSearch.DialogResult = true;
            IsBusy = true;
            Complete(this);
            client.GetListByCriteriaCompleted += client_GetListByCriteriaCompleted;
            client.GetListByCriteriaAsync(criteria, expression, page);
        }

        private void client_GetListByCriteriaCompleted(object sender, GetListByCriteriaCompletedEventArgs e)
        {
            client.GetListByCriteriaCompleted -= client_GetListByCriteriaCompleted;
            PurchaseOrders = new PagedCollectionView(e.Result);
            if (RecordCount != e.recordCount)
            {
                RecordCount = e.recordCount;
                CreatePageNumber();
            }
            IsBusy = false;
        }

        private void GetWarehouseList()
        {
            WarehouseClient.GetAllWarehouseCompleted += WarehouseClient_GetAllWarehouseCompleted;
            WarehouseClient.GetAllWarehouseAsync();
        }

        private void WarehouseClient_GetAllWarehouseCompleted(object sender, GetAllWarehouseCompletedEventArgs e)
        {
            WarehouseClient.GetAllWarehouseCompleted -= WarehouseClient_GetAllWarehouseCompleted;
            Warehouses = e.Result;

            if (PurchaseOrder != null)
            {
                if (PurchaseOrder.Warehouse == null) return;
                PurchaseOrder.Warehouse =
                    Warehouses.FirstOrDefault(s => s.KodeWarehouse == PurchaseOrder.Warehouse.KodeWarehouse);
            }
        }

        private void GetCurrencyList()
        {
            CurrencyClient.GetAllCurrencyCompleted += CurrencyClient_GetAllCurrencyCompleted;
            CurrencyClient.GetAllCurrencyAsync();
        }

        private void CurrencyClient_GetAllCurrencyCompleted(object sender, GetAllCurrencyCompletedEventArgs e)
        {
            CurrencyClient.GetAllCurrencyCompleted -= CurrencyClient_GetAllCurrencyCompleted;
            Currencys = e.Result;
            PurchaseOrder.Currency = Currencys.FirstOrDefault(x => x.CurrencyCode == "Rp");
            PurchaseOrder.Kurs = 1;

            if (PurchaseOrder != null)
            {
                if (PurchaseOrder.Currency == null) return;
                PurchaseOrder.Currency =
                    Currencys.FirstOrDefault(s => s.CurrencyCode == PurchaseOrder.Currency.CurrencyCode);
            }
        }


        private void CreatePageNumber()
        {
            Pages = new ObservableCollection<int>();
            for (int i = 0; i < RecordCount; i++)
            {
                Pages.Add(i);
            }
            PageSources = new PagedCollectionView(Pages);
        }


        private void PageIndexChanged(Object pageIndex)
        {
            //Jika Pertama kali jangan di Getlagi
            PurchaseOrder = null;
            if (PurchaseOrders != null && CurrentPage != (int) pageIndex)
            {
                CurrentPage = (int) pageIndex;
                if (mode == Mode.Search)
                    PurchaseOrderSearch(criteria, expression, (int)pageIndex + 1);
                else if (String.IsNullOrEmpty(PropertySort))
                    GetList((int) pageIndex + 1, null);
                else GetList((int) pageIndex + 1, PropertySort);
            }
        }

        public bool CanPageIndexChanged(Object param)
        {
            return true;
        }

        public bool CanSave(Object param)
        {
            return true;
        }

        public bool CanNew(Object param)
        {
            return true;
        }

        public bool CanEdit(Object param)
        {
            return true;
        }

        public bool CanUnload(Object param)
        {
            return true;
        }

        public bool CanSearch(Object param)
        {
            return true;
        }

        public bool CanSearchResult(Object param)
        {
            return true;
        }

        public bool CanCancelCommand(Object param)
        {
            return true;
        }


        public void Release(Object param)
        {
            param = null;
            PurchaseOrder = null;
            OrderType = null;
            PropertySort = null;
            mode = Mode.Idle;
        }


        public void Refresh()
        {
            if (PurchaseOrders == null)
                GetList(1, null);
            else
                Complete(this);
        }


        public void Validate(string error = null)
        {
            Errors = new List<string>();
            //if (string.IsNullOrEmpty(PurchaseOrder.PONumber))
            //    Errors.Add("Nomor PO tidak boleh kosong");
            if (PurchaseOrder.Supplier == null)
                Errors.Add("Supplier harus diisi!");
            if (PurchaseOrder.Warehouse == null)
                Errors.Add("Warehouse harus diisi!");
            if (PurchaseOrder.Currency == null)
                Errors.Add("Currency harus diisi!");
            if (PurchaseOrder.TglTerimaBarang == null)
                Errors.Add("TglTerima belum diisi!");
            if (!string.IsNullOrEmpty(error))
                Errors.Add(error);
            MessageVisibility = Errors.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
        }

        public void Cancel(Object param)
        {
            MessageBoxResult res = MessageBox.Show("Are You Sure Want to Cancel ?", "Confirmation",
                                                   MessageBoxButton.OKCancel);
            if (res == MessageBoxResult.OK)
            {
                if (!IsUsed) ClearTransaksi(mode);
                mode = Mode.Idle;
                Navigation.MyNavigation.GoBack();
            }
        }

        private void GetLastNoMutasi()
        {
            client = new PurchaseOrderServicesClient();
            client.GetLastPONoCompleted +=
                client_GetLastNoMutasiCompleted;
            client.GetLastPONoAsync();
        }

        private void client_GetLastNoMutasiCompleted(object sender, GetLastPONoCompletedEventArgs e)
        {
            client.GetLastPONoCompleted -=
                client_GetLastNoMutasiCompleted;
            string res = e.Result;
            string formatSO = "0000";
            string kodeSO;
            if (e.Result.Length <= 4)
            {
                res = formatSO;
                kodeSO = e.Result;
            }
            else
            {
                res = e.Result.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries)[2];
                kodeSO = e.Result.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries)[0];
            }
            string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(res) + 1).ToString().Length) +
                           (int.Parse(res) + 1);

            //PurchaseOrder = new PurchaseOrderDTO();
            PurchaseOrder.PONumber = kodeSO + "/" + DateTime.Now.Year + "/" + soNum;
        }

        public void GetSupplier(Object param)
        {
            SupplierClient.GetSupplierListCompleted += SupplierClient_GetSupplierListCompleted;
            SupplierClient.GetSupplierListAsync(param.ToString());
        }

        private void SupplierClient_GetSupplierListCompleted(object sender, GetSupplierListCompletedEventArgs e)
        {
            SupplierClient.GetSupplierListCompleted -= SupplierClient_GetSupplierListCompleted;
            Suppliers = e.Result;
            SupplierVisibility = Visibility.Visible;
            EventAggregator.PublishMessage("SupplierSelect", string.Empty);
        }

        public void SupplierSelected(Object param)
        {
            PurchaseOrder.Supplier = ((SupplierDTO) param);
            SupplierVisibility = Visibility.Collapsed;
        }

        public void GetSubgroupByName(Object param)
        {
            var PODetail = (PurchaseOrderDetailDTO) param;
            SubGroupClient.GetSubGroupListByNameCompleted += SubgroupClient_GetSubGroupListByNameCompleted;
            SubGroupClient.GetSubGroupListByNameAsync(PODetail.Name, PODetail);
        }

        private void SubgroupClient_GetSubGroupListByNameCompleted(object sender,
                                                                   GetSubGroupListByNameCompletedEventArgs e)
        {
            SubGroupClient.GetSubGroupListByNameCompleted -= SubgroupClient_GetSubGroupListByNameCompleted;
            var Subgroups = new ObservableCollection<SubGroupDTO>((from s in e.Result
                                                                   select
                                                                       new SubGroupDTO
                                                                           {
                                                                               SubGroupID = s.SubGroupID,
                                                                               SubGroupName = s.SubGroupName
                                                                           }));
            var poDetail = (PurchaseOrderDetailDTO) e.UserState;
            poDetail.Subgroups = Subgroups;
        }

        public void Print(Object param)
        {
            Navigation.MyNavigation.Navigate(new Uri("/PurchaseOrder/PrintPreviewPO", UriKind.Relative));
            Navigation.Args = param;
        }

        public void SendEmail(Object param)
        {
            ChooseDestination chooseDestination = new ChooseDestination();
            chooseDestination.Show();
            EventAggregator.RegisterMessage("SendDestination", (x) =>
            {
                IsBusy = true;
                client.SendEmailCompleted += client_SendEmailCompleted;
                client.SendEmailAsync(param as PurchaseOrderDTO, (x as WarehouseDTO).EmailFolder);
            });

        }

        private void client_SendEmailCompleted(object sender, PurchaseOrderServices.SendEmailCompletedEventArgs e)
        {
            IsBusy = false;
            client.SendEmailCompleted -= client_SendEmailCompleted;
            if (e.Result) MessageBox.Show("Pengiriman Selesai");
        }

        public void CekTransaksi()
        {
            ApplicationService.IsTransactionUsedCompleted += ApplicationService_IsTransactionUsedCompleted;
            if (string.IsNullOrEmpty(PurchaseOrder.PONumber))
            {
                ApplicationService.IsTransactionUsedAsync(PurchaseOrder.ToString(), GlobalVar.User, mode);
                GlobalVar.CurrentTransaction = PurchaseOrder.ToString();
            }
            else
            {
                ApplicationService.IsTransactionUsedAsync(PurchaseOrder.PONumber, GlobalVar.User, mode);
                GlobalVar.CurrentTransaction = PurchaseOrder.PONumber;
            }
        }

        private void ApplicationService_IsTransactionUsedCompleted(object sender, IsTransactionUsedCompletedEventArgs e)
        {
            ApplicationService.IsTransactionUsedCompleted -= ApplicationService_IsTransactionUsedCompleted;
            IsUsed = e.Result;
            mode = (Mode) e.UserState;
            if (IsUsed)
            {
                MessageBox.Show("Transaksi sedang digunakan!");
                if (mode == Mode.Add) //If Add Mode
                {
                    mode = Mode.Idle;
                    Navigation.MyNavigation.Navigate(new Uri("/PurchaseOrder/Index", UriKind.Relative));
                }
                else //Edit Mode just view Only
                {
                    IsEnabled = false;
                }
            }
        }

        private void ClearTransaksi(Mode mode)
        {
            ApplicationService.ClearTransactionCompleted += ApplicationService_ClearTransactionCompleted;
            if (mode == Mode.Add)
                ApplicationService.ClearTransactionAsync(PurchaseOrder.ToString(), GlobalVar.User);
            else
                ApplicationService.ClearTransactionAsync(PurchaseOrder.PONumber, GlobalVar.User);
        }

        private void ApplicationService_ClearTransactionCompleted(object sender, AsyncCompletedEventArgs e)
        {
            ApplicationService.ClearTransactionCompleted -= ApplicationService_ClearTransactionCompleted;
        }

        public void CloseStatus()
        {
               MessageBoxResult res = MessageBox.Show("Are You Sure Want to Close this PurchaseOrder ?", "Confirmation",
                                                   MessageBoxButton.OKCancel);
               if (res == MessageBoxResult.OK)
               {
                   client.UpdateStatusCompleted += new EventHandler<AsyncCompletedEventArgs>(client_UpdateStatusCompleted);
                   client.UpdateStatusAsync(PurchaseOrder, Status.Close);
               }
        }

        void client_UpdateStatusCompleted(object sender, AsyncCompletedEventArgs e)
        {
            client.UpdateStatusCompleted -= new EventHandler<AsyncCompletedEventArgs>(client_UpdateStatusCompleted);
            MessageBox.Show("Update PO Status finished!");
        }
    }


    public class PurchaseOrderWrapViewModel : ViewModelBase
    {
        private readonly SubGroupServiceClient SubGroupClient;
        private readonly PurchaseOrderServicesClient client;
        private List<string> _DiscTypes;
        private ObservableCollection<InventoryDTO> _Inventorys;
        private PurchaseOrderDetailDTO _PurchaseOrderDetail;
        private ObservableCollection<SubGroupDTO> _SubGroups;


        public PurchaseOrderWrapViewModel()
        {
            if (!DesignerProperties.IsInDesignTool)
            {
                EditCommand = new DelegateCommand(Edit, CanEditCommand);
                DeleteCommand = new DelegateCommand(Delete, CanDeleteCommand);
                client = new PurchaseOrderServicesClient();
                SubGroupClient = new SubGroupServiceClient();
                AddDetailCommand = new DelegateCommand(AddPurchaseOrderDetail, CanAddDetailCommand);
                DeleteDetailCommand = new DelegateCommand(DeletePurchaseOrderDetail, CanDeleteDetailCommand);
                GetTotalDetailCommand = new DelegateCommand(GetTotalDetail, CanGetTotalDetailCommand);
                GetPpnCommand = new DelegateCommand(GetPpn, CanGetPpnCommand);
                GetTotalDiscountCommand = new DelegateCommand(GetTotalDiscount, CanGetTotalDiscount);
                DiscTypes = new List<string>();
                DiscTypes.Add("%");
                DiscTypes.Add("val");
                if (PurchaseOrderViewModel.mode == Mode.Add || PurchaseOrderViewModel.mode == Mode.Edit)
                {
                }
            }
        }

        public PurchaseOrderViewModel PurchaseOrderViewModel { get; set; }


        public ICommand EditCommand { get; set; }
        public ICommand DeleteCommand { get; set; }
        public ICommand AddDetailCommand { get; set; }
        public ICommand DeleteDetailCommand { get; set; }


        public ObservableCollection<SubGroupDTO> SubGroups
        {
            get { return _SubGroups; }
            private set
            {
                if (SubGroups == value) return;
                _SubGroups = value;
                FirePropertyChanged("SubGroups");
            }
        }


        public PurchaseOrderDetailDTO PurchaseOrderDetail
        {
            get { return _PurchaseOrderDetail; }
            private set
            {
                if (PurchaseOrderDetail == value) return;
                _PurchaseOrderDetail = value;
                FirePropertyChanged("PurchaseOrderDetail");
            }
        }

        public ICommand GetInventoryCommand { get; set; }
        public ICommand GetQtyUnitCommand { get; set; }

        public List<string> DiscTypes
        {
            get { return _DiscTypes; }
            private set
            {
                if (DiscTypes == value) return;
                _DiscTypes = value;
                FirePropertyChanged("DiscTypes");
            }
        }

        public ICommand GetTotalDetailCommand { get; set; }
        public ICommand GetPpnCommand { get; set; }
        public ICommand GetTotalDiscountCommand { get; set; }

        public bool CanEditCommand(Object param)
        {
            return true;
        }

        public bool CanDeleteCommand(Object param)
        {
            return true;
        }

        public bool CanAddDetailCommand(Object param)
        {
            return true;
        }

        public bool CanDeleteDetailCommand(Object param)
        {
            return true;
        }


        public void Edit(Object param)
        {
            PurchaseOrderViewModel.mode = Mode.Edit;
            Navigation.MyNavigation.Navigate(new Uri("/PurchaseOrder/frmAdd", UriKind.Relative));
            Navigation.Args = param;
        }

        public void Delete(Object param)
        {
            DeleteConfirmation deleteConfirmation = new DeleteConfirmation();
            deleteConfirmation.Show();
            EventAggregator.RegisterMessage("ApprovalSucceeded", (x) =>
            {
                deleteConfirmation.Close();
                client.DeleteCompleted += client_DeleteCompleted;
                client.DeleteAsync((PurchaseOrderDTO)param);
            });

        }

        private void client_DeleteCompleted(object sender, AsyncCompletedEventArgs e)
        {
            client.DeleteCompleted -= client_DeleteCompleted;
            MessageBox.Show("Delete Success!");
            PurchaseOrderViewModel.mode = Mode.Idle;
            var VM = new PurchaseOrderViewModel();
        }


        public void GetSubGroupList()
        {
            SubGroupClient.GetListByCriteriaCompleted +=
                SubGroupClient_GetListByCriteriaCompleted;
            SubGroupClient.GetListByCriteriaAsync(new Dictionary<string, object>(), null, 1);
        }

        private void SubGroupClient_GetListByCriteriaCompleted(object sender,
                                                               SubGroupServices.GetListByCriteriaCompletedEventArgs e)
        {
            SubGroups = e.Result;
            if (PurchaseOrderViewModel.PurchaseOrder != null)
            {
                foreach (
                    PurchaseOrderDetailDTO PurchaseOrderDetail in
                        PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails)
                {
                    if (PurchaseOrderDetail.SubGroup == null) continue;
                    PurchaseOrderDetail.SubGroup =
                        SubGroups.FirstOrDefault(s => s.SubGroupID == PurchaseOrderDetail.SubGroup.SubGroupID);
                }
            }
        }


        public void AddPurchaseOrderDetail(Object param)
        {
            PurchaseOrderDetail = new PurchaseOrderDetailDTO();
            PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails.Add(PurchaseOrderDetail);
        }

        public void DeletePurchaseOrderDetail(Object param)
        {
            var PurchaseOrderDetail = (PurchaseOrderDetailDTO) param;
            if (PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails.Count > 1)
            {
                if (param == null)
                {
                    int count = PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails.Count;
                    PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails.Remove(PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails[count-1]);
                }else
                {
                    PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails.Remove(PurchaseOrderDetail);
                }
               
                GetTotalDetail(PurchaseOrderDetail);
            }
        }

     


        public bool CanGetInventoryCommand(Object param)
        {
            return true;
        }

        public bool CanGetQtyUnit(Object param)
        {
            return true;
        }

        public bool CanGetTotalDetailCommand(Object param)
        {
            return true;
        }

        public bool CanGetPpnCommand(Object param)
        {
            return true;
        }


        public void GetTotalDetail(Object param)
        {
            PurchaseOrderDetail = (PurchaseOrderDetailDTO) param;

            foreach (var poDetail in PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails)
            {
                if (poDetail.DiscountType != "%")
                    poDetail.TotalDetail = ((poDetail.Qty * poDetail.Price) - poDetail.Discount) ;
                else
                    poDetail.TotalDetail = (poDetail.Qty * (poDetail.Price -
                                                             (poDetail.Price *
                                                              poDetail.Discount / 100))) ;
            }

            PurchaseOrderViewModel.PurchaseOrder.SubTotal =
               PurchaseOrderViewModel.PurchaseOrder.PurchaseOrderDetails.Sum(p => p.TotalDetail);
            if (PurchaseOrderViewModel.PurchaseOrder.DiscountType != "%")
                PurchaseOrderViewModel.PurchaseOrder.AfterDiscount = PurchaseOrderViewModel.PurchaseOrder.SubTotal -
                                                                     PurchaseOrderViewModel.PurchaseOrder.Discount;
            else
                PurchaseOrderViewModel.PurchaseOrder.AfterDiscount = PurchaseOrderViewModel.PurchaseOrder.SubTotal -
                                                                     (PurchaseOrderViewModel.PurchaseOrder.SubTotal *
                                                                      PurchaseOrderViewModel.PurchaseOrder.Discount / 100);
            if (PurchaseOrderViewModel.PurchaseOrder.IsPpn)
                PurchaseOrderViewModel.PurchaseOrder.Ppn = PurchaseOrderViewModel.PurchaseOrder.AfterDiscount * 10 / 100;
            if (PurchaseOrderViewModel.PurchaseOrder.Ppn > 0)
                PurchaseOrderViewModel.PurchaseOrder.IsPpn = true;
            PurchaseOrderViewModel.PurchaseOrder.Total =
                PurchaseOrderViewModel.PurchaseOrder.AfterDiscount + PurchaseOrderViewModel.PurchaseOrder.Ppn;
        }

      

        public void GetPpn(Object param)
        {
            var PurchaseOrder = (PurchaseOrderDTO) param;
            if (PurchaseOrder.IsPpn)
            {
                PurchaseOrder.Ppn = PurchaseOrder.AfterDiscount*10/100;
                PurchaseOrder.Total = PurchaseOrder.AfterDiscount + PurchaseOrder.Ppn;
            }
            else
            {
                PurchaseOrder.Ppn = 0;
                PurchaseOrder.Total = PurchaseOrder.AfterDiscount + PurchaseOrder.Ppn;
            }
        }

        public bool CanGetTotalDiscount(Object param)
        {
            return true;
        }

        public void GetTotalDiscount(Object param)
        {
            var PurchaseOrder = (PurchaseOrderDTO) param;
            if (PurchaseOrder.PurchaseOrderDetails != null)
                PurchaseOrder.SubTotal =
                    PurchaseOrder.PurchaseOrderDetails.Sum(p => p.TotalDetail);
            if (PurchaseOrder.DiscountType != "%")
                PurchaseOrder.AfterDiscount = PurchaseOrder.SubTotal - PurchaseOrder.Discount;
            else
                PurchaseOrder.AfterDiscount = PurchaseOrder.SubTotal -
                                              (PurchaseOrder.SubTotal*PurchaseOrder.Discount/100);
            if (PurchaseOrder.IsPpn)
                PurchaseOrder.Ppn = PurchaseOrder.AfterDiscount*10/100;
            if (PurchaseOrder.Ppn > 0)
                PurchaseOrder.IsPpn = true;
            PurchaseOrder.Total =
                PurchaseOrder.AfterDiscount + PurchaseOrder.Ppn;
        }
    }
}